/**
 * index_iterator.cpp
 */
#include <cassert>

#include "storage/index/index_iterator.h"

namespace bustub {

/*
 * NOTE: you can change the destructor/constructor method here
 * set your own input parameters
 */
INDEX_TEMPLATE_ARGUMENTS
INDEXITERATOR_TYPE::IndexIterator() = default;

INDEX_TEMPLATE_ARGUMENTS
INDEXITERATOR_TYPE::IndexIterator(BPlusTreePage *leaf_page, BufferPoolManager *buffer_pool_manager, int pos)
    : tree_page_(leaf_page), pos_(pos), buffer_pool_manager_(buffer_pool_manager) {
  page_size_ = tree_page_->GetSize();
  page_id_ = tree_page_->GetPageId();
}

INDEX_TEMPLATE_ARGUMENTS
INDEXITERATOR_TYPE::~IndexIterator() = default;  // NOLINT

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::IsEnd() const -> bool { return page_id_ == INVALID_PAGE_ID; }

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::operator*() -> const MappingType & {
  auto *leaf_page = static_cast<LeafPage *>(tree_page_);
  return leaf_page->MappingAt(pos_);
}

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::operator++() -> INDEXITERATOR_TYPE & {
  if (page_id_ == INVALID_PAGE_ID) {
    return *this;
  }
  if (++pos_ < page_size_) {
    return *this;
  }
  auto *leaf_page = static_cast<LeafPage *>(tree_page_);
  auto next_page_id = leaf_page->GetNextPageId();
  // 释放当前leaf_page
  buffer_pool_manager_->UnpinPage(tree_page_->GetPageId(), true);
  // 判断是否达到end
  if (next_page_id == INVALID_PAGE_ID) {
    page_id_ = INVALID_PAGE_ID;
    tree_page_ = nullptr;
  } else {
    // 取下一个leaf_page, 重置metadata
    Page *page = buffer_pool_manager_->FetchPage(next_page_id);
    tree_page_ = reinterpret_cast<BPlusTreePage *>(page->GetData());
    pos_ = 0;
    page_size_ = tree_page_->GetSize();
    page_id_ = next_page_id;
  }
  return *this;
}

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::operator!=(const IndexIterator &itr) const -> bool {
  if (itr.IsEnd()) {
    return page_id_ != INVALID_PAGE_ID;
  }
  return (pos_ != itr.pos_) || (page_id_ != itr.page_id_);
}

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::operator==(const IndexIterator &itr) const -> bool {
  if (itr.IsEnd()) {
    return page_id_ == INVALID_PAGE_ID;
  }
  return (pos_ == itr.pos_) && (page_id_ == itr.page_id_);
}

template class IndexIterator<GenericKey<4>, RID, GenericComparator<4>>;

template class IndexIterator<GenericKey<8>, RID, GenericComparator<8>>;

template class IndexIterator<GenericKey<16>, RID, GenericComparator<16>>;

template class IndexIterator<GenericKey<32>, RID, GenericComparator<32>>;

template class IndexIterator<GenericKey<64>, RID, GenericComparator<64>>;

}  // namespace bustub
